package com.iflytek.autoCompareTool.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iflytek.autoCompareTool.common.Constants;
import com.iflytek.autoCompareTool.model.OutputInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 对比请求的Json对象结果，封装为结果集对象
 *
 * @author llchen12
 * @date 2018/6/5
 */
public class Comparator {

    private static Logger logger = LoggerFactory.getLogger(Comparator.class);

    private OutputInfo outputInfo;

    private int answer;

    public Comparator(OutputInfo outputInfo) {
        this.outputInfo = outputInfo;
    }


    /**
     * 初始化不需要比较的信息
     */
    public Comparator(String uid, String usrid, String appid, String parameter, String userData, String text, String baseUrl, String cmpUrl, String fileName, int answer) {
        this.outputInfo = new OutputInfo();
        outputInfo.setAppid(appid);
        outputInfo.setUsrid(usrid);
        outputInfo.setParameter(parameter);
        outputInfo.setUid(uid);
        outputInfo.setUserData(userData);
        outputInfo.setText(text);
        outputInfo.setBaseUrl(baseUrl);
        outputInfo.setC1Url(cmpUrl);
        outputInfo.setFileName(fileName);
        this.answer = answer;
    }

    public OutputInfo getOutputInfo() {
        return outputInfo;
    }

    public void setOutputInfo(OutputInfo outputInfo) {
        this.outputInfo = outputInfo;
    }

    public int getAnswer() {
        return answer;
    }

    public void setAnswer(int answer) {
        this.answer = answer;
    }

    /**
     * 两个环境对比
     *
     * @param baseJo 基准JSON
     * @param c1Jo   对比JSON
     * @throws Exception
     */
    public void envCmpEnv(JSONObject baseJo, JSONObject c1Jo) {
        formatOutputInfo(baseJo, "base");
        formatOutputInfo(c1Jo, "c1");

        //******对比业务********
        compareService(outputInfo.getBaseService(), outputInfo.getClService());
        //******对比操作********
        compareOperation(outputInfo.getBaseOperation(), outputInfo.getClOperation());
        //******对比semantic,type为0表示两个环境对比********
        JSONObject bSemantic;
        JSONObject bSemanticNew = null;
        JSONObject baseSemantic = outputInfo.getBaseSemantic();
        if (baseSemantic != null) {
            String bStr = baseSemantic.toJSONString();
            bSemantic = JSON.parseObject(bStr);
            bSemanticNew = (JSONObject) bSemantic.clone();
        }
        JSONObject cSemantic;
        JSONObject cSemanticNew = null;
        JSONObject clSemantic = outputInfo.getClSemantic();
        if (clSemantic != null) {
            String cStr = clSemantic.toJSONString();
            cSemantic = JSON.parseObject(cStr);
            cSemanticNew = (JSONObject) cSemantic.clone();
        }

        compareSemantic(bSemanticNew, cSemanticNew, 0);

        //******对比Answer********
        compareAnswer(outputInfo.getBaseAnswer(), outputInfo.getClAnswer());
    }


    /**
     * 标注和对比环境
     *
     * @param jo         对比环境json
     * @param eService
     * @param eSemantic
     * @param eOpeartion
     */
    public void eptCmpEnv(JSONObject jo, String eService, String eSemantic, String eOpeartion, String eAnswer) {
        formatOutputInfo(jo, "c1");
        //标注时rc4比较
        if ("rc4".equals(eService) || StringUtils.isEmpty(eService)) {
            eService = "rc=4";
        }

        outputInfo.setBaseService(eService);
        outputInfo.setBaseSemantic(StringUtils.isEmpty(eSemantic) ? null : JSONObject.parseObject(eSemantic));
        outputInfo.setBaseOperation(eOpeartion);
        outputInfo.setBaseAnswer(eAnswer);

        //******对比业务********/
        compareService(outputInfo.getBaseService(), outputInfo.getClService());
        //******对比操作********/
        compareOperation(outputInfo.getBaseOperation(), outputInfo.getClOperation());
        //******对比semantic,type为1表示标注和对比环境(因需要在比较对象上操作，为了不影响原对象故重新生成JSON对象)********/
        JSONObject bSemantic = null;
        if (outputInfo.getBaseSemantic() != null) {
            bSemantic = JSONObject.parseObject(eSemantic);
        }
        JSONObject cSemantic = null;
        if (outputInfo.getClSemantic() != null) {
            String cStr = outputInfo.getClSemantic().toJSONString();
            cSemantic = JSONObject.parseObject(cStr);
        }
        compareSemantic(bSemantic, cSemantic, 1);
        //******对比Answer********/
        compareAnswer(outputInfo.getBaseAnswer(), outputInfo.getClAnswer());
    }

    /**
     * 初始化要对比的信息
     *
     * @param jo
     * @param env
     * @throws Exception
     */
    private void formatOutputInfo(JSONObject jo, String env) {

        if (StringUtils.equals("base", env)) {
            outputInfo.setBaseService(getService(jo));
            outputInfo.setBaseOperation(getOpeation(jo));
            outputInfo.setBaseSemantic(getSemantic(jo));
            outputInfo.setBaseAnswer(getAnswer(jo));
            outputInfo.setBaseUuid(getUuid(jo));
            outputInfo.setBaseSid(getSid(jo));
        } else if (StringUtils.equals("c1", env)) {
            outputInfo.setClService(getService(jo));
            outputInfo.setClOperation(getOpeation(jo));
            outputInfo.setClSemantic(getSemantic(jo));
            outputInfo.setClAnswer(getAnswer(jo));
            outputInfo.setC1Uuid(getUuid(jo));
            outputInfo.setC1Sid(getSid(jo));
        }
    }


    /**
     * 获取Service
     */
    private String getService(JSONObject jsonObject) {
        if (jsonObject.containsKey("service")) {
            return jsonObject.get("service").toString();
        }
        if (jsonObject.containsKey("rc")) {
            return "rc=" + jsonObject.get("rc").toString();
        }
        return "";
    }

    /**
     * 获取answer
     */
    private String getAnswer(JSONObject jsonObject) {
        Object answer = jsonObject.get("answer");
        if (answer != null) {
            if (answer instanceof JSONObject) {
                JSONObject ans = (JSONObject) answer;
                if (ans.containsKey("text")){
                    return ans.getString("text");
                }else {
                    return ans.toString();
                }
            } else {
                return answer.toString();
            }
        }
        return "";
    }

    /**
     * 获取semantic
     */
    private JSONObject getSemantic(JSONObject json) {
        if (!json.containsKey("service") || !json.containsKey("semantic")) {
            return null;
        } else {
            if (json.containsKey("semantic") && json.get("semantic") instanceof JSONObject) {
                return json.getJSONObject("semantic");
            } else if (json.containsKey("semantic") && json.get("semantic") instanceof JSONArray) {
                return json.getJSONArray("semantic").getJSONObject(0);
            } else {
                return JSON.parseObject("{}");
            }
        }
    }

    /**
     * 获取operation
     */
    private String getOpeation(JSONObject jsonObject) {
        if (jsonObject.containsKey("operation")) {
            return jsonObject.get("operation").toString();
        }
        if (jsonObject.containsKey("semantic") && jsonObject.get("semantic") instanceof JSONArray) {
            return jsonObject.getJSONArray("semantic").getJSONObject(0).get("intent").toString();
        }
        return "";
    }

    /**
     * 读取uuid
     */
    private String getUuid(JSONObject jsonObject) {
        if (jsonObject.containsKey("uuid")) {
            return jsonObject.get("uuid").toString();
        }
        return "";
    }

    /**
     * 读取sid
     */
    private String getSid(JSONObject jsonObject) {
        if (jsonObject.containsKey("sid")) {
            return jsonObject.get("sid").toString();
        }
        return "";
    }

    /**
     * 对比service
     *
     * @param baseService
     * @param cService
     */
    private void compareService(String baseService, String cService) {
        // 两个服务的对比
        if (baseService == null || cService == null) {
            if (baseService != null || cService != null) {
                outputInfo.setCmpService(Constants.FALSE);
                outputInfo.setFinalResult(Constants.DIFFER);
                return;
            } else {
                outputInfo.setCmpService(Constants.NULL);
                return;
            }
        }
        String baseAnswer = outputInfo.getBaseAnswer();
        String clAnswer = outputInfo.getClAnswer();
        //你想坐飞机还是火车？answer对比为true时忽略service的对比
        if (("train".equals(baseService) || "flight".equals(baseService))
                && ("train".equals(cService) || "flight".equals(cService))
                && baseAnswer != null
                && baseAnswer.equals(clAnswer)) {
            outputInfo.setCmpService(Constants.TRUE);
            return;
        }
        //你想控制什么设备？answer对比为true忽略service全部为家居的对比
        if (baseService.contains("smartHome") && cService.contains("smartHome")
                && baseAnswer != null
                && baseAnswer.equals(clAnswer)) {
            outputInfo.setCmpService(Constants.TRUE);
            return;
        }


        if (!baseService.equals(cService)) {
            outputInfo.setCmpService(Constants.FALSE);
            outputInfo.setFinalResult(Constants.DIFFER);
            return;
        }
        outputInfo.setCmpService(Constants.TRUE);
    }


    /**
     * 对比operation
     */
    private void compareOperation(String baseOp, String cOp) {
        // 对比2个操作
        if (isNull(baseOp) || isNull(cOp)) {
            if (!isNull(baseOp) || !isNull(cOp)) {
                outputInfo.setCmpOperation(Constants.FALSE);
                outputInfo.setFinalResult(Constants.DIFFER);
                return;
            } else {
                outputInfo.setCmpOperation(Constants.NULL);
                return;
            }
        }
        if (!baseOp.equals(cOp)) {
            outputInfo.setCmpOperation(Constants.FALSE);
            return;
        }
        outputInfo.setCmpOperation(Constants.TRUE);
    }


    /**
     * 对比semantic,type为0表示两个环境对比,type为1表示标注和对比环境
     *
     * @param baseSemantic
     * @param c1Semantic
     * @param type
     */
    private void compareSemantic(JSONObject baseSemantic, JSONObject c1Semantic, int type) {
        //||baseSemantic.isEmpty()||c1Semantic.isEmpty()
        if (baseSemantic == null || c1Semantic == null) {
            if (baseSemantic != null || c1Semantic != null) {
                outputInfo.setCmpSemantic(Constants.FALSE);
                outputInfo.setFinalResult(Constants.DIFFER);
                return;
            } else {
                outputInfo.setCmpSemantic(Constants.NULL);
                return;
            }
        }

        /*
        1、当sementic.slots.startDate.timeOrig内容是“现在”时，忽略sementic.slots.startDate.time的对比。
        2、sementic.slots.band与sementic.slots.artist提取的内容一致时，判断为true。
        3、与标注对比时,直接忽略：
            (1)、sementic.slots.startDate.date,
            (2)、sementic.slots.startDate.endDate,
            (3)、sementic.slots.datetime.time
        4、sementic.slots.datetime.timeOrig内容是“现在”时，忽略sementic.slots.datetime.time的对比
        */
        semanticCompareAndRemove(baseSemantic, type);
        semanticCompareAndRemove(c1Semantic, type);

        if (!baseSemantic.equals(c1Semantic)) {
            outputInfo.setCmpSemantic(Constants.FALSE);
            outputInfo.setFinalResult(Constants.DIFFER);
            return;
        }
        outputInfo.setCmpSemantic(Constants.TRUE);

    }


    private void semanticCompareAndRemove(JSONObject sementic, int type) {
        if (sementic.get("slots") instanceof JSONObject) {
            // sementic.slots.datetime.timeOrig内容是“现在”时，移除sementic.slots.datetime.time的
            if (sementic.containsKey("slots") && sementic.getJSONObject("slots").containsKey("datetime")
                    && sementic.getJSONObject("slots").getJSONObject("datetime").containsKey("timeOrig") && "现在".equals(
                    sementic.getJSONObject("slots").getJSONObject("datetime").get("timeOrig").toString())) {
                sementic.getJSONObject("slots").getJSONObject("datetime").remove("time");
            }

            // 当sementic.slots.startDate.timeOrig内容是“现在”时，移除sementic.slots.startDate.time
            if (sementic.containsKey("slots") && sementic.getJSONObject("slots").containsKey("startDate")
                    && sementic.getJSONObject("slots").getJSONObject("startDate").containsKey("timeOrig")
                    && "现在".equals(
                    sementic.getJSONObject("slots").getJSONObject("startDate").get("timeOrig").toString())) {
                sementic.getJSONObject("slots").getJSONObject("startDate").remove("time");
            }
            // sementic.slots.band与sementic.slots.artist提取的内容一致时,移除这两个属性
            if (sementic.containsKey("slots") && sementic.getJSONObject("slots").containsKey("band")
                    && sementic.getJSONObject("slots").containsKey("artist") && sementic.getJSONObject("slots")
                    .getJSONObject("band").equals(sementic.getJSONObject("slots").getJSONObject("artist"))) {
                sementic.getJSONObject("slots").remove("band");
                sementic.getJSONObject("slots").remove("artist");
            }

            if (sementic.containsKey("slots")) {
                sementic.getJSONObject("slots").remove("is_athena");
            }

            if (sementic.containsKey("slots")) {
                sementic.getJSONObject("slots").remove("operation");
            }
        }

        if (!sementic.containsKey("slots")) {
            sementic.put("slots", new JSONObject());
        }


        sementic.remove("entrypoint");
        sementic.remove("score");

        /*
         * 与标注对比时,直接忽略： (1)、sementic.slots.startDate.date,
         * (2)、sementic.slots.startDate.endDate, (3)、sementic.slots.datetime.time
         */
        if (type == 1) {
            if (sementic.get("slots") instanceof JSONObject) {
                if (sementic.containsKey("slots") && sementic.getJSONObject("slots").containsKey("startDate")) {
                    sementic.getJSONObject("slots").getJSONObject("startDate").remove("date");
                    sementic.getJSONObject("slots").getJSONObject("startDate").remove("endDate");
                }
                if (sementic.containsKey("slots") && sementic.getJSONObject("slots").containsKey("datetime")) {
                    sementic.getJSONObject("slots").getJSONObject("datetime").remove("time");
                }
            }
        }

        if (sementic.get("slots") instanceof JSONObject) {
            if (sementic.containsKey("slots") && sementic.getJSONObject("slots").containsKey("datetime")) {
                sementic.getJSONObject("slots").getJSONObject("datetime").remove("date");
                sementic.getJSONObject("slots").getJSONObject("datetime").remove("time");
            }
        }
    }

    /**
     * 对比answer
     *
     * @param baseAnswer
     * @param cAnswer
     */
    private void compareAnswer(String baseAnswer, String cAnswer) {
        if (isNull(baseAnswer) || isNull(cAnswer)) {
            if (!isNull(baseAnswer) || !isNull(cAnswer)) {
                outputInfo.setCmpAnswer(Constants.FALSE);
                if (answer == 1) {
                    outputInfo.setFinalResult(Constants.DIFFER);
                }
                return;
            } else {
                outputInfo.setCmpAnswer(Constants.NULL);
                return;
            }
        }
        if (!baseAnswer.equals(cAnswer)) {
            outputInfo.setCmpAnswer(Constants.FALSE);
            if (answer == 1) {
                outputInfo.setFinalResult(Constants.DIFFER);
            }
            return;
        }
        outputInfo.setCmpAnswer(Constants.TRUE);
    }

    private boolean isNull(String str) {
        return str == null || "".equals(str);
    }


}
